package service

import (
	"fmt"
	"sen-golang-study/go_game_study/hero_story_go_server/game_server/internal/domain/session/entity"
	"sen-golang-study/go_game_study/hero_story_go_server/game_server/internal/domain/session/repository"
	"time"
)

// SessionDomainService 会话领域服务
type SessionDomainService struct {
	sessionRepo repository.SessionRepository
}

// NewSessionDomainService 创建会话领域服务
func NewSessionDomainService(sessionRepo repository.SessionRepository) *SessionDomainService {
	return &SessionDomainService{
		sessionRepo: sessionRepo,
	}
}

// CreateSession 创建会话
func (s *SessionDomainService) CreateSession(sessionID string, gatewayID, remoteSessionID uint32, clientIPAddr string) (*entity.Session, error) {
	if len(sessionID) == 0 {
		return nil, fmt.Errorf("session ID cannot be empty")
	}

	// 检查会话是否已存在
	existingSession, err := s.sessionRepo.GetBySessionID(sessionID)
	if err != nil {
		return nil, fmt.Errorf("failed to check existing session: %w", err)
	}
	if existingSession != nil {
		return nil, fmt.Errorf("session already exists: %s", sessionID)
	}

	// 创建新会话
	session := entity.NewSession(sessionID, gatewayID, remoteSessionID)
	session.SetClientIPAddr(clientIPAddr)

	// 保存会话
	err = s.sessionRepo.Save(session)
	if err != nil {
		return nil, fmt.Errorf("failed to save session: %w", err)
	}

	return session, nil
}

// GetSession 获取会话
func (s *SessionDomainService) GetSession(sessionID string) (*entity.Session, error) {
	if len(sessionID) == 0 {
		return nil, fmt.Errorf("session ID cannot be empty")
	}

	return s.sessionRepo.GetBySessionID(sessionID)
}

// GetSessionByUserID 根据用户ID获取会话
func (s *SessionDomainService) GetSessionByUserID(userID uint32) (*entity.Session, error) {
	if userID == 0 {
		return nil, fmt.Errorf("user ID cannot be zero")
	}

	return s.sessionRepo.GetByUserID(userID)
}

// BindUserToSession 绑定用户到会话
func (s *SessionDomainService) BindUserToSession(sessionID string, userID uint32) error {
	if len(sessionID) == 0 {
		return fmt.Errorf("session ID cannot be empty")
	}
	if userID == 0 {
		return fmt.Errorf("user ID cannot be zero")
	}

	// 检查用户是否已绑定到其他会话
	existingSession, err := s.sessionRepo.GetByUserID(userID)
	if err != nil {
		return fmt.Errorf("failed to check existing user session: %w", err)
	}
	if existingSession != nil && existingSession.GetSessionID() != sessionID {
		// 如果用户已绑定到其他会话，先解绑
		existingSession.UnbindUser()
		err = s.sessionRepo.Update(existingSession)
		if err != nil {
			return fmt.Errorf("failed to unbind user from existing session: %w", err)
		}
	}

	// 获取目标会话
	session, err := s.sessionRepo.GetBySessionID(sessionID)
	if err != nil {
		return fmt.Errorf("failed to get session: %w", err)
	}
	if session == nil {
		return fmt.Errorf("session not found: %s", sessionID)
	}

	// 绑定用户
	session.BindUser(userID)

	// 更新会话
	err = s.sessionRepo.Update(session)
	if err != nil {
		return fmt.Errorf("failed to update session: %w", err)
	}

	return nil
}

// UnbindUserFromSession 从会话解绑用户
func (s *SessionDomainService) UnbindUserFromSession(sessionID string) error {
	if len(sessionID) == 0 {
		return fmt.Errorf("session ID cannot be empty")
	}

	// 获取会话
	session, err := s.sessionRepo.GetBySessionID(sessionID)
	if err != nil {
		return fmt.Errorf("failed to get session: %w", err)
	}
	if session == nil {
		return fmt.Errorf("session not found: %s", sessionID)
	}

	// 解绑用户
	session.UnbindUser()

	// 更新会话
	err = s.sessionRepo.Update(session)
	if err != nil {
		return fmt.Errorf("failed to update session: %w", err)
	}

	return nil
}

// CloseSession 关闭会话
func (s *SessionDomainService) CloseSession(sessionID string) error {
	if len(sessionID) == 0 {
		return fmt.Errorf("session ID cannot be empty")
	}

	// 获取会话
	session, err := s.sessionRepo.GetBySessionID(sessionID)
	if err != nil {
		return fmt.Errorf("failed to get session: %w", err)
	}
	if session == nil {
		return fmt.Errorf("session not found: %s", sessionID)
	}

	// 关闭会话
	session.Close()

	// 更新会话
	err = s.sessionRepo.Update(session)
	if err != nil {
		return fmt.Errorf("failed to update session: %w", err)
	}

	return nil
}

// UpdateSessionActivity 更新会话活跃时间
func (s *SessionDomainService) UpdateSessionActivity(sessionID string) error {
	if len(sessionID) == 0 {
		return fmt.Errorf("session ID cannot be empty")
	}

	// 获取会话
	session, err := s.sessionRepo.GetBySessionID(sessionID)
	if err != nil {
		return fmt.Errorf("failed to get session: %w", err)
	}
	if session == nil {
		return fmt.Errorf("session not found: %s", sessionID)
	}

	// 更新活跃时间
	session.UpdateLastActiveTime()

	// 更新会话
	err = s.sessionRepo.Update(session)
	if err != nil {
		return fmt.Errorf("failed to update session: %w", err)
	}

	return nil
}

// CleanExpiredSessions 清理过期会话
func (s *SessionDomainService) CleanExpiredSessions(timeoutMs int64) error {
	return s.sessionRepo.CleanExpiredSessions(timeoutMs)
}

// GetActiveSessions 获取所有活跃会话
func (s *SessionDomainService) GetActiveSessions() ([]*entity.Session, error) {
	return s.sessionRepo.GetActiveSessions()
}

// GetSessionStats 获取会话统计信息
func (s *SessionDomainService) GetSessionStats() (map[string]interface{}, error) {
	totalCount, err := s.sessionRepo.GetSessionCount()
	if err != nil {
		return nil, fmt.Errorf("failed to get total session count: %w", err)
	}

	activeCount, err := s.sessionRepo.GetActiveSessionCount()
	if err != nil {
		return nil, fmt.Errorf("failed to get active session count: %w", err)
	}

	stats := map[string]interface{}{
		"total_sessions":  totalCount,
		"active_sessions": activeCount,
		"timestamp":       time.Now().UnixMilli(),
	}

	return stats, nil
}

// RemoveSession 移除会话
func (s *SessionDomainService) RemoveSession(sessionID string) error {
	if len(sessionID) == 0 {
		return fmt.Errorf("session ID cannot be empty")
	}

	return s.sessionRepo.Delete(sessionID)
}
